package cn.itsource.hrm.service.impl;

import cn.itsource.hrm.domain.VipBase;
import cn.itsource.hrm.domain.VipUser;
import cn.itsource.hrm.domain.dto.RegisterDto;
import cn.itsource.hrm.domain.dto.SendSmsCodeDto;
import cn.itsource.hrm.exception.GloabException;
import cn.itsource.hrm.mapper.VipBaseMapper;
import cn.itsource.hrm.mapper.VipUserMapper;
import cn.itsource.hrm.service.IVerifycodeService;
import cn.itsource.hrm.util.StrUtils;
import cn.itsource.hrm.util.ValidityUtils;
import cn.itsource.hrm.util.VerifyCodeUtils;
import cn.itsource.hrm.util.encrypt.MD5;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;



@Service
@Slf4j
public class VerifycodeServiceImpl implements IVerifycodeService {
    
    // 手机号的后缀
    private static String SMS_POST_REGIST = "regist";   
    private static String SMS_POST_LOGIN = "login"; 
    
    @Autowired
    private VipUserMapper userMapper;    
    
    @Autowired
    private VipBaseMapper baseMapper;
    
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    
    @Override
    public String getImageCode(String key) {
        //有前端传递的key
        ValidityUtils.isNotNull(key,"请刷新页面重试！！");
        //1. 生成base64
        //1.2 通过工具类生成验证码
        String code = VerifyCodeUtils.generateVerifyCode(4);
        //通过工具类，把验证码，转换成图片base64
        try {
            String base64 = VerifyCodeUtils.verifyCode(120, 50, code);
        //2. 存到redis
        //通过redisTemplate key, 验证码
            redisTemplate.opsForValue().set(key,code,10, TimeUnit.MINUTES);
           
        //返回base64的验证码
            return base64;   
        } catch (IOException e) {
            e.printStackTrace();
            throw new GloabException("后台生成验证码故障，我们在殴打程序员！！！");
        }
        
    }

    /**
     * 发送短信
     * @param smsCodeDto
     */
    @Override
    public void sendSmsCode(SendSmsCodeDto smsCodeDto) {
        //1. 判断参数： 图像imageCode，imageCodeKey， mobile
        String imageCodeKey = smsCodeDto.getImageCodeKey();
        String imageCode = smsCodeDto.getImageCode();
        String mobile = smsCodeDto.getMobile();
        
        //2. 判断图形验证码是否正确:
        
        //通过 imageCodeKey 到Redis中获取，判断
        String old_code = (String) redisTemplate.opsForValue().get(imageCodeKey);
        ValidityUtils.isNotNull(old_code, "图像验证码过期，请刷新页面重试！！");
        //错误： 错误提示，图形验证码异常
        ValidityUtils.isTrue(old_code.toLowerCase().equals(imageCode.trim().toLowerCase()),"图像验证码不正确");
        //正确，移除之前的图形验证码
        redisTemplate.delete(imageCodeKey);
        
        // 3. 判断手机是否曾经发送验证码：
        String smskey = mobile + SMS_POST_REGIST;
        RedisSaveSMS oldSms = (RedisSaveSMS) redisTemplate.opsForValue().get(smskey);
        //获取当前时间，和Redis中保存的时间
        Date now = new Date();
        String sms_code ="";
        if(oldSms==null){
           //生成 4位随机数 value 短信验证码
            sms_code = StrUtils.getRandomString(4);
       }else{
        //存在，判断时间间隔要大于60S
           Date oldSmsTime = oldSms.getTime();
            if(DateUtils.addMinutes(oldSmsTime,1).getTime() > now.getTime()){
                //没有超过60s时间 提示不要重复提交
                throw new GloabException("超过过于频繁，太快了");
            }
            //超过60s,取出来复用
            sms_code = oldSms.getValue();
        }
        //保存到redis: key(mobile + SMS_POST_REGIST)   redis对象(phone, value, 当前时间)，过期时间（5分钟）
        redisTemplate.opsForValue().set(smskey, new RedisSaveSMS(mobile,sms_code,now),5,TimeUnit.MINUTES);
        

        //发送短信验证码
        log.info("短信验证码已发送： {}",sms_code);


    }

    @Override
    public void regist(RegisterDto registerDto) {
        String mobile = registerDto.getMobile();
        String password = registerDto.getPassword();
        String smsCode = registerDto.getSmsCode();

        //1. 判断手机号是否注册
        VipUser user = userMapper.selectByPhone(mobile);
        //（如果注册提示，已注册）
        ValidityUtils.isNull(user, "手机号已注册！！");
        
        //2. 没有注册： 在判断短信验证码,
        // 通过 mobile 去Redis 获取 old_sms_Code
        String key = mobile+SMS_POST_REGIST;
        RedisSaveSMS oldSms = (RedisSaveSMS) redisTemplate.opsForValue().get(key);
        
        //不存在：提示过期了
        ValidityUtils.isNotNull(oldSms, "验证码过期了,请重新获取短信验证");

        //存在：判断是否正确
        ValidityUtils.isTrue(oldSms.getValue().equals(smsCode.trim()),"短信验证码不正确");
        
        //3. 注册 准备用户数据：
        user = new VipUser();
        //password 加盐加密
        String slat = MD5.getRandomCode(18);
        user.setPassword( MD5.getMD5(password+slat));
        user.setSalt(slat);
        
        //，昵称， 电话号码
        user.setPhone(mobile);
        user.setNickName(mobile);
        //，注册时间，
        long now = new Date().getTime();
        user.setCreateTime(now);
        user.setUpdateTime(now);
        //用户手机认证状态
        user.addBite(VipUser.PHONE_AUTHENTICATE);

        userMapper.insert(user);
        
        //初始化用户基本信息表
        VipBase vipBase = new VipBase();
        vipBase.setSsoId(user.getId());
        vipBase.setCreateTime(now);
        vipBase.setUpdateTime(now);
        vipBase.setRegTime(now);
        baseMapper.insert(vipBase);
        
        //注册成功，删除短信验证码
        redisTemplate.delete(key);

    }


    
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class RedisSaveSMS{
    private String phone;
    private String value;
    private Date time;
}